<template>
  <transition appear name="q-transition--jump-down">
    <div v-if="isLoad" :class="gridCls" :style="{ width: `calc(100% / ${gridCols})` }"
         class="q-table__grid-item grid-style-transition relative-position q-pa-sm">
      <q-card class="fit bg-grey-2 column no-wrap overflow-hidden">
        <div class="q-table__grid-card-shade absolute-bottom-right"></div>
        <q-card-section
          class="q-table__grid-header relative-position row justify-between items-center q-px-md q-py-sm text-white">
          <slot v-if="selection" :props="props" name="selection"></slot>
          <div :class="selection ? 'q-pl-sm' : ''" class="col text-weight-medium">
            <div v-if="topLeftColumn" class="text-bold relative-position">
              <template v-if="topLeftColumn.useTag && !isEmpty(topLeftColumn.value)">
                <q-badge :color="getColor(topLeftColumn)" class="q-badge-dot absolute-badge-dot" rounded></q-badge>
                <span class="q-ml-md">{{ getLabel(topLeftColumn) }}</span>
              </template>
              <qx-tooltip v-else :rowsNum="topLeftColumn.rowsNum || 2">{{ getLabel(topLeftColumn) }}</qx-tooltip>
            </div>
            <template v-else>{{ `NO.${props.rowIndex + 1}` }}</template>
          </div>
          <q-space></q-space>
          <div v-if="topRightColumn" class="text-bold relative-position">
            <template v-if="topRightColumn.useTag && !isEmpty(topRightColumn.value)">
              <q-badge :color="getColor(topRightColumn)" class="q-badge-dot absolute-badge-dot" rounded></q-badge>
              <span class="q-ml-md">{{ getLabel(topRightColumn) }}</span>
            </template>
            <qx-tooltip v-else :rowsNum="topRightColumn.rowsNum || 2">{{ getLabel(topRightColumn) }}</qx-tooltip>
          </div>
          <slot name="topRight"></slot>
        </q-card-section>
        <q-list :class="bodyRowCls" class="col q-gutter-y-xs q-py-sm" @click.stop="handleClickRow('rowClick')"
                @dblclick.stop="handleClickRow('rowDbClick')">
          <q-item v-for="column in filterList" :key="column.name" class="items-center q-px-md q-py-none">
            <q-item-label v-if="!(nonHeader || column.nonHeader)" :class="headerCellCls(column)"
                          :style="{ width: `${column.headerWidth || headerWidth || 80}px`}"
                          class="q-grid-th text-body2 text-grey-8 row no-wrap items-center justify-start q-mr-sm"
                          @click.stop="handleClickRow('cellHeaderClick', column)">
              <slot v-if="column.headerSlot" :name="column.field + 'H'" :row="column"></slot>
              <qx-tooltip v-else>{{ column.label }}</qx-tooltip>
            </q-item-label>
            <q-item-label :class="cellCls(column)" :style="getTdPaddingLeft(column)"
                          class="col q-grid-td row items-center justify-start text-body2 text-dark text-weight-medium no-margin"
                          @click.stop="handleClickRow('cellClick', column)"
                          @dblclick.stop="handleClickRow('cellDbClick', column)">
              <template v-if="column.__has_child">
                <q-icon :name="props.expand ? 'keyboard_arrow_down' : 'keyboard_arrow_right'" :size="expandIconSize"
                        class="text-bold absolute expand-btn" @click.stop="toggleExpand(props)" />
              </template>
              <template v-if="column.slot">
                <slot :name="column.field"></slot>
              </template>
              <template v-else>
                <template v-if="column.useTag && !isEmpty(column.value)">
                  <q-badge :color="getColor(column)" class="q-badge-dot absolute-badge-dot" rounded></q-badge>
                  <span class="q-ml-md">{{ getLabel(column) }}</span>
                </template>
                <qx-tooltip v-else :rowsNum="column.rowsNum || 2">{{ getLabel(column) }}</qx-tooltip>
              </template>
            </q-item-label>
          </q-item>
        </q-list>
        <q-separator v-if="!!$slots.menu" class="gradient-separator-x full-width"></q-separator>
        <div key="menu" class="q-table__grid-footer q-pa-sm row q-gutter-sm relative-position" @click.stop=""
             @dblclick.stop="">
          <slot name="menu"></slot>
        </div>
      </q-card>
    </div>
  </transition>
</template>

<script setup>
import { getLabel, getResult } from 'components/tableUtils.js'
import { useTimeout } from 'quasar'
import { getColorByValue, isEmpty } from 'src/utils/utils.js'
import { computed, onMounted, ref } from 'vue'

const prop = defineProps({
  childKey: String, treeNode: String, gridCols: Number, selection: String, cardslot: Boolean, rowClick: Function,
  nonHeader: Boolean, canExpand: Boolean, cellClick: Function, dbRowClick: Function, cellDbClick: Function,
  headerClick: Function, rowCls: [String, Function], headerWidth: [String, Number],
  props: { type: Object, default: () => ({}) }
})
const emits = defineEmits(['toggleExpand', 'dbRowClick']), { registerTimeout, removeTimeout } = useTimeout()

const isLoad = ref(false)
const expandIconSize = ref('1.125rem')
const childKey = computed(() => prop.childKey || 'children')
const opacity = computed(() => prop.props.selected ? 0.75 : 0.15)
const gridCls = computed(() => prop.cardslot ? 'q-table__grid-custom' : 'q-table__grid-normal')
const hasChild = (row = {}, column = {}) => {
  if (prop.canExpand && column.isExpand) return true
  if (!prop.treeNode) return
  if (!row[childKey.value]?.length) return false
  return column.field === prop.treeNode
}
const topLeftColumn = computed(() => (prop.props || {}).cols.find(el => el.topLeft))
const topRightColumn = computed(() => (prop.props || {}).cols.find(el => el.topRight))
const filterList = computed(() => {
  const { cols, row } = prop.props || {}
  return cols.filter(el => !['index', 'menu'].includes(el.name) && !el.topRight && !el.topLeft).map(column => {
    return { ...column, __has_child: hasChild(row, column) }
  })
})
const bodyRowCls = computed(() => {
  const { dbRowClick, props = {}, rowClick, rowCls } = prop
  const cls = `${getResult(rowCls, props)}`
  if (rowClick || dbRowClick) return `${cls} cursor-pointer cursor-hover`
  return cls
})
const headerCellCls = computed(() => {
  return (column = {}) => {
    const cls = 'text-body1 text-capitalize '
    if (column.headerClasses) return cls + getResult(column.headerClasses, prop.props)
    if (column.headerClick) return cls + 'cursor-pointer text-primary cursor-hover'
    return cls
  }
})
const cellCls = computed(() => {
  return (column = {}) => {
    const cls = 'relative-position '
    if (column.__has_child) return cls + 'can-expand-cell cursor-pointer cursor-hover'
    if (column.cellClick || column.cellDbClick) return cls + 'cursor-pointer text-primary cursor-hover'
    return cls
  }
})
onMounted(() => {
  const { pageIndex = 0 } = prop.props
  registerTimeout(() => {
    isLoad.value = true
    removeTimeout && removeTimeout()
  }, 2 * pageIndex + 5)
})
const getColor = ({ tagColors, value, options = [], props: rowProps }) => {
  if (!tagColors) return getColorByValue(value, options, rowProps, 'primary')
  return tagColors[value] || 'primary'
}
const getTdPaddingLeft = column => {
  const { props = {}, treeNode = '' } = prop
  if (!treeNode || column.field !== prop.treeNode) return {}
  const { row = {} } = props
  let PL = 0
  if (!row[childKey.value]?.length) PL = 16
  return { 'padding-left': `calc(${expandIconSize.value} + ${Number(row.level || 0) * 10 + PL}px)` }
}
const toggleExpand = props => emits('toggleExpand', props, childKey.value)
const handleClickRow = (action, column = {}) => {
  const { cellClick, cellDbClick, dbRowClick, headerClick, props = {}, rowClick } = prop
  const { colsMap, row, rowIndex = 0 } = props
  if (action === 'rowClick') return rowClick && rowClick(row, column, colsMap, rowIndex)
  if (action === 'rowDbClick') return dbRowClick && dbRowClick(row, column, colsMap, rowIndex)
  if (action === 'cellHeaderClick') return headerClick && headerClick(row, column, colsMap, rowIndex)
  if (action === 'cellClick') {
    if (column.__has_child) return toggleExpand(props)
    if (column.cellClick) return column.cellClick(row, column, rowIndex)
    if (cellClick) return cellClick(row, column, rowIndex)
    if (rowClick) return rowClick(row, column, colsMap, rowIndex)
  } else if (action === 'cellDbClick') {
    if (column.cellDbClick) return column.cellDbClick(row, column, rowIndex)
    if (cellDbClick) return cellDbClick(row, column, rowIndex)
    if (dbRowClick) return dbRowClick(row, column, colsMap, rowIndex)
  }
}
</script>

<style lang="scss" scoped>
.q-table__grid-normal::before {
  opacity: v-bind(opacity);
}
</style>